//////////////////////////////////////////////////////////////////////////
/// Copyright (C), 1998-2016, rytec Corporation. All rights reserved.
/// \file       ImageViewer.cpp
/// \brief      
/// \author     wyf
/// \version    0.95
/// \date       2020-3
//////////////////////////////////////////////////////////////////////////

#include "ImageViewer.h"

#include "ui_ImageViewer.h"
#include <QContextMenuEvent>
#include <QDesktopWidget>
#include <QApplication>
#include <QStyleOption>
#include <QFileDialog>
#include <QPainter>
#include <QTimer>
#include <QMenu>

CRyImageViewer::CRyImageViewer(QWidget* parent)
    : mUi(new Ui_ImageViewer())
    , mScaleTextTimer(new QTimer(this))
    , mOffset(0, 0)
    , mRotation(0.0)
    , mScaleRatio(1.0)
    , mPressedButton(Qt::NoButton)
    , mScaleTextVisible(false)
{
    // 设置窗体属性
    mUi->setupUi(this);
    mUi->mToolsWidget->setVisible(false);
    mUi->mCloseButton->setVisible(false);
    mUi->mToolsWidget->installEventFilter(this);
    mUi->mCloseButton->installEventFilter(this);

    setCursor(Qt::OpenHandCursor);
    setAttribute(Qt::WA_TranslucentBackground, true);
    setWindowFlags(Qt::Widget | Qt::FramelessWindowHint);

    mImage.load("E:\\tt\\Small.JPG");
    mScaleTextTimer->setSingleShot(true);

    // 设置默认窗体大小
    if (!mImage.isNull())
    {
        QSize defaultSize;
        QSize imageSize = mImage.size();
        QSize fixedSize = QApplication::desktop()->size();
        defaultSize.setWidth(qMin(imageSize.width(), fixedSize.width()));
        defaultSize.setHeight(qMin(imageSize.height(), fixedSize.height()));
        setFixedSize(defaultSize);
    }

    // 关联事件
    connect(mScaleTextTimer, &QTimer::timeout, this, &CRyImageViewer::onScaleTextTimerOut);
    connect(mUi->mResetButton, &QPushButton::clicked, this, &CRyImageViewer::onResetButtonClicked);
    connect(mUi->mFullScreenButton, &QPushButton::clicked, this, &CRyImageViewer::onFullScreenButtonClicked);
    connect(mUi->mRotateButton, &QPushButton::clicked, this, &CRyImageViewer::onRotateButtonClicked);
    connect(mUi->mSaveButton, &QPushButton::clicked, this, &CRyImageViewer::onSaveButtonClicked);
    connect(mUi->mCloseButton, &QPushButton::clicked, this, &CRyImageViewer::close);
}

CRyImageViewer::~CRyImageViewer()
{
    delete mScaleTextTimer;
    delete mUi;
}

void CRyImageViewer::enterEvent(QEvent* event)
{
    mUi->mToolsWidget->setVisible(true);
    mUi->mCloseButton->setVisible(true);
}

void CRyImageViewer::leaveEvent(QEvent* event)
{
    mUi->mToolsWidget->setVisible(false);
    mUi->mCloseButton->setVisible(false);
}

void CRyImageViewer::paintEvent(QPaintEvent *event)
{
    QStyleOption opt;
    opt.init(this);

    // 绘制控件
    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing, true);
    style()->drawPrimitive(QStyle::PE_Widget, &opt, &painter, this);

    // 绘制图片
    if (!mImage.isNull())
    {
        // 根据窗口计算应该显示的图片的大小
        qreal imageWidth = qMin(mImage.width(), width());
        qreal imageHeight = imageWidth / (qreal(mImage.width()) / mImage.height());
        imageHeight = qMin(imageHeight, qreal(height()));
        imageWidth = imageHeight * (qreal(mImage.width()) / mImage.height());
        QRectF picRect(-imageWidth / 2, -imageHeight / 2, imageWidth, imageHeight);

        // 绘制图像
        painter.save();
        painter.translate(width() / 2 + mOffset.x(), height() / 2 + mOffset.y());
        painter.scale(mScaleRatio, mScaleRatio);
        painter.rotate(mRotation);
        painter.drawImage(picRect, mImage);
        painter.restore();

        // 绘制缩放文本
        if (mScaleTextVisible)
        {
            QFont font = painter.font();
            font.setBold(true);
            font.setPixelSize(20);
            painter.setFont(font);
            painter.setPen(Qt::white);

            QFontMetrics fontMetrics = painter.fontMetrics();
            QRectF textBound = fontMetrics.boundingRect("1000%");
            textBound.moveCenter(rect().center());

            QPainterPath path;
            textBound.adjust(10, 10, 20, 20);
            path.addRoundedRect(textBound, 5, 5);
            painter.fillPath(path, QBrush(QColor(50, 50, 50, 150)));

            QString scaleText = QString("%1%").arg(int(mScaleRatio * 100));
            painter.drawText(textBound, Qt::AlignCenter, scaleText);
        }
    }
}

void CRyImageViewer::wheelEvent(QWheelEvent* event)
{
    QWidget::wheelEvent(event);
    scaleImage(event->delta() > 0 ? 1.2 : 0.8, &(event->pos()));
    update();
}

void CRyImageViewer::mousePressEvent(QMouseEvent* event)
{
    QWidget::mousePressEvent(event);
    if (event->button() == Qt::RightButton)
        setCursor(Qt::SizeAllCursor);
    else
        setCursor(Qt::ClosedHandCursor);

    mPressedButton = event->button();
    mPreMousePos = event->globalPos();
}

void CRyImageViewer::mouseMoveEvent(QMouseEvent* event)
{
    QWidget::mouseMoveEvent(event);
    if (mPressedButton == Qt::LeftButton)
    {
        mOffset.setX(mOffset.x() + event->globalPos().x() - mPreMousePos.x());
        mOffset.setY(mOffset.y() + event->globalPos().y() - mPreMousePos.y());
        setCursor(Qt::ClosedHandCursor);
        update();
    }
    else if (mPressedButton == Qt::RightButton)
    {
        if (!isMaximized())
        {
            QPoint point;
            point.setX(event->globalPos().x() - mPreMousePos.x());
            point.setY(event->globalPos().y() - mPreMousePos.y());
            move(x() + point.x(), y() + point.y());
        }
        setCursor(Qt::SizeAllCursor);
    }
    else
    {
        setCursor(Qt::OpenHandCursor);
    }
    mPreMousePos = event->globalPos();
}

void CRyImageViewer::mouseReleaseEvent(QMouseEvent *event)
{
    QWidget::mouseReleaseEvent(event);
    setCursor(Qt::OpenHandCursor);
    mPressedButton = Qt::NoButton;
}

bool CRyImageViewer::eventFilter(QObject* watched, QEvent* event)
{
    if (watched == mUi->mToolsWidget || watched == mUi->mCloseButton)
    {
        if (event->type() == QEvent::Enter)
            setCursor(Qt::ArrowCursor);
        else if (event->type() == QEvent::Leave)
            setCursor(Qt::OpenHandCursor);
    }
    return QWidget::eventFilter(watched, event);
}

void CRyImageViewer::onResetButtonClicked()
{
    mOffset = QPoint(0, 0);
    mScaleRatio = 1.0;
    update();
}

void CRyImageViewer::onFullScreenButtonClicked()
{
    return isMaximized() ? showNormal() : showMaximized();
}

void CRyImageViewer::onRotateButtonClicked()
{
    mRotation += 90;
    update();
}

void CRyImageViewer::onSaveButtonClicked()
{
    if (!mImage.isNull())
    {
        QString fileName = QFileDialog::getSaveFileName(this, tr("另存为"), "",
            tr("Images (*.png *.bmp *.jpg *.tif *.xpm)"));
        mImage.save(fileName, QFileInfo(fileName).suffix().toStdString().c_str());
    }
}

void CRyImageViewer::onScaleTextTimerOut()
{
    mScaleTextVisible = false;
    update();
}

void CRyImageViewer::scaleImage(qreal ratio, QPoint* centerIn)
{
    Q_UNUSED(centerIn);
    mScaleRatio *= ratio;
    mScaleRatio = qBound(0.1, mScaleRatio, 10.0);

    mScaleTextTimer->start(1000);
    mScaleTextVisible = true;
    update();
}
